package com.study.crypto.basic.signer;

import com.study.crypto.basic.asn1.oid.CMSObjectIdentifiers;
import com.study.crypto.basic.signer.utils.CMSUtils;
import org.apache.http.util.Asserts;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CRL;

/**
 * 使用先计算摘要，再进行签名方式进行 sm2 签名。国家标准 GB/T 35275 签名数据类型(signedData)
 * @author Songjin
 * @since 2022-04-25 13:22
 */
public class PKCS7GmDeferredSigner extends Signer {
    
    private final Certificate certificate;
    private final CRL[] crls;
    /** 原文数据。本实现采用不带原文方式组装 SignedData 结构 */
    private final byte[] contentData;
    
    public PKCS7GmDeferredSigner(Certificate certificate, CRL[] crls, byte[] contentData) {
        this.certificate = certificate;
        this.crls = crls;
        this.contentData = contentData;
    }
    
    @Override
    public byte[] sign(byte[] hashedData, PrivateKey privateKey) throws IOException, CryptoException, GeneralSecurityException, CMSException {
        Asserts.notNull(privateKey, "privateKey");
        Asserts.notNull(certificate, "certificate");
    
        // 组装带属性的 asn1 结构
        ASN1ObjectIdentifier dataOid = CMSObjectIdentifiers.data;
        ASN1EncodableVector attrVector = CMSUtils.getAttrVector(dataOid, hashedData);
        DERSet derRSet = new DERSet(attrVector);
        byte[] attrBytes = derRSet.getEncoded(ASN1Encoding.DER);

        CipherParameters parameters = ECUtil.generatePrivateKeyParameter(privateKey);
        SM2Signer sm2Signer = new SM2Signer();
        sm2Signer.init(true, parameters);
        sm2Signer.update(attrBytes, 0, attrBytes.length);
        byte[] signVal = sm2Signer.generateSignature();
        return CMSUtils.getAttrSignedData(certificate, signVal, crls, attrVector);
    }
    
    @Override
    public boolean verify(byte[] digest, byte[] signature, PublicKey publicKey) throws GeneralSecurityException {
        return false;
    }
}
